package deptController

import (
	"myRbac/models"
	"myRbac/utils"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

type DeptController struct{}

// @Summary 部门查询
// @Description 分页查询部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param page query string false "页码"
// @Param pageSize query string false "尺寸"
// @Param name query string false "部门名"
// @Success 200 {object} models.ResultByPage[models.Department] "查询成功"
// @Success 401 {object} models.ErrorResult "查询失败"
// @Router /dept [get]
// @Security JWT
func (d DeptController) QueryDepts(ctx *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("pageSize", "10"))
	nameStr := ctx.DefaultQuery("name", "")
	name := "%" + nameStr + "%"
	// 定义承载体
	deptList := []models.Department{}
	models.DB.Model(&models.Department{}).Where("is_delete!=1 AND name like ?", name).Limit(pageSize).Offset(pageSize * (page - 1)).Find(&deptList)
	var total int64
	// 查询条目
	models.DB.Table("departments").Where("is_delete!=1 AND name like ?", name).Count(&total)
	// 返回值约束
	result := &models.ResultByPage[models.Department]{
		Msg:      "ok",
		Code:     "200",
		Total:    total,
		Page:     page,
		PageSize: pageSize,
		Result:   deptList,
	}
	ctx.JSON(http.StatusOK, result)
}

// @Summary 部门查询
// @Description 根据Id查询部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param id path string true "部门id"
// @Success 200 {object} models.ResultCommon[models.Department] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /dept/{id} [get]
// @Security JWT
func (d DeptController) QueryDeptById(ctx *gin.Context) {
	dept := &models.Department{}
	user_id := ctx.Param("id")
	models.DB.Where("id=? AND is_delete!=1", user_id).First(&dept)
	if dept.Id == 0 {
		ctx.JSON(http.StatusOK, &models.ResultCommon[string]{
			Msg:    "查询失败",
			Code:   "400",
			Result: "",
		})
	} else {
		ctx.JSON(http.StatusOK, &models.ResultCommon[models.Department]{
			Msg:    "查询成功",
			Code:   "200",
			Result: *dept,
		})
	}
}

// @Summary 新增部门
// @Description 传入json，新增部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param deptInfo body models.Department true "部门信息"
// @Success 200 {object} models.AddResult "新增成功"
// @fail 400 {object} models.ErrorResult "数据错误"
// @fail 401 {object} models.AddResult "新增失败"
// @Router /dept [post]
// @Security JWT
func (d DeptController) AddDept(ctx *gin.Context) {
	dept := &models.Department{}
	// 绑定json数据
	if err := ctx.ShouldBindJSON(&dept); err != nil {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "数据错误",
			Code:   "400",
			Result: nil,
		})
	} else {
		dept.CreateTime = utils.TimeFormatter(time.Now())
		result := models.DB.Model(&models.Department{}).Create(&dept)
		if result.RowsAffected != 1 {
			ctx.JSON(http.StatusOK, &models.AddResult{
				Msg:    "插入失败",
				Code:   "400",
				Result: result.RowsAffected,
			})
		} else {
			ctx.JSON(http.StatusOK, &models.AddResult{
				Msg:    "插入成功",
				Code:   "200",
				Result: result.RowsAffected,
			})
		}
	}
}

// @Summary 更新部门
// @Description 传入json，更新部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param deptInfo body models.Department true "部门信息"
// @Success 200 {object} models.UpdateResult[models.Department] "更新成功"
// @fail 400 {object} models.ErrorResult "数据错误"
// @fail 401 {object} models.ErrorResult "用户不存在"
// @fail 402 {object} models.AddResult "更新失败"
// @Router /dept [put]
// @Security JWT
func (d DeptController) UpdateDept(ctx *gin.Context) {
	// 获取提交的用户修改信息
	var dept models.Department
	// 绑定json数据
	if err := ctx.ShouldBindJSON(&dept); err != nil {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "数据绑定失败",
			Code:   "400",
			Result: err,
		})
		return
	}
	// 绑定部门信息
	dept_old := &models.Department{}
	// 查找部门信息
	models.DB.First(&dept_old, dept.Id)
	if dept_old.Id == 0 {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "该部门不存在",
			Code:   "400",
			Result: nil,
		})
		return
	}
	result := models.DB.Model(&dept_old).Updates(dept)
	if result.RowsAffected != 1 {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "更新失败",
			Code:   "400",
			Result: result.Error,
		})
	} else {
		ctx.JSON(http.StatusOK, &models.UpdateResult[models.Department]{
			Msg:    "更新成功",
			Code:   "200",
			Result: dept,
		})
	}
}

// @Summary 删除部门
// @Description 传入json，批量删除部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param deptsIds body models.DeleteParams true "部门id合集"
// @Success 200 {object} models.DeleteResult "更新成功"
// @fail 400 {object} models.ErrorResult "数据错误"
// @fail 401 {object} models.DeleteResult "删除失败"
// @Router /dept [delete]
// @Security JWT
func (d DeptController) DeleteDept(ctx *gin.Context) {
	// 绑定参数实例
	ids := &models.DeleteParams{}
	// 定义模型实例
	var dept models.Department
	if err := ctx.ShouldBindJSON(&ids); err != nil {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "数据绑定失败",
			Code:   "400",
			Result: err,
		})
	} else {
		// 假的删
		result := models.DB.Model(&dept).Where("id IN (?)", ids.Ids).Update("is_delete", 1)
		if result.RowsAffected != 0 {
			ctx.JSON(http.StatusOK, &models.DeleteResult{
				Msg:    "删除成功",
				Code:   "200",
				Result: ids.Ids,
			})
		} else {
			ctx.JSON(http.StatusOK, &models.DeleteResult{
				Msg:    "删除失败",
				Code:   "400",
				Result: []int{0},
			})
		}
	}
}

// @Summary 子部门查询
// @Description 根据父Id查询子部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param id path string true "父部门id"
// @Success 200 {object} models.ResultCommon[[]models.Department] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /dept/subset/{id} [get]
// @Security JWT
func (d DeptController) QueryDeptSubset(ctx *gin.Context) {
	// 断言成那个类型
	id := ctx.Param("id")
	// 声明承载体
	deptList := []models.Department{}
	models.DB.Model(&models.Department{}).Where("fid=? AND is_delete!=1", id).Find(&deptList)
	ctx.JSON(http.StatusOK, &models.ResultCommon[[]models.Department]{
		Msg:    "查询成功",
		Code:   "200",
		Result: deptList,
	})
}

// @Summary 部门查询
// @Description 树状查询子部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param page query string false "页码"
// @Param pageSize query string false "尺寸"
// @param name query string false "部门名"
// @Success 200 {object} models.ResultByPage[models.Department] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /dept/tree [get]
// @Security JWT
func (d DeptController) QueryDeptTree(ctx *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("pageSize", "10"))
	nameStr := ctx.DefaultQuery("name", "")
	name := "%" + nameStr + "%"
	var departments []models.Department
	if err := models.DB.Preload("Children", "is_delete=0 AND name like ?", name).Preload("Children.Children", "is_delete=0 AND name like ?", name).Where("fid=0 AND is_delete=0 AND name like ?", name).Limit(pageSize).Offset(pageSize * (page - 1)).Find(&departments).Error; err != nil {
		ctx.JSON(http.StatusOK, models.ResultCommon[string]{
			Msg:    "查询失败",
			Code:   "400",
			Result: "",
		})
	} else {
		var total int64
		models.DB.Table("departments").Where("is_delete!=1").Count(&total)
		ctx.JSON(http.StatusOK, models.ResultByPage[models.Department]{
			Msg:    "查询成功",
			Code:   "200",
			Total:  total,
			Result: departments,
		})
	}
}

// @Summary 部门查询
// @Description 查询所有上级部门
// @Tags 部门管理
// @Accept json
// @Produce json
// @Param id path string false "当前部门id"
// @Success 200 {object} models.ResultCommon[models.Department] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /dept/upper/:id [get]
// @Security JWT
func (d DeptController) QueryDeptUpper(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	if result, _ := GetAncestorDept(id); result != nil {
		ctx.JSON(http.StatusOK, models.ResultCommon[[]models.Department]{
			Msg:    "ok",
			Code:   "200",
			Result: result,
		})
	} else {
		ctx.JSON(http.StatusOK, models.ResultCommon[string]{
			Msg:    "no",
			Code:   "200",
			Result: "",
		})
	}
}

func GetAncestorDept(id int) ([]models.Department, error) {
	var dept []models.Department
	err := models.DB.Model(&models.Department{}).Where("id = ? AND is_delete = 0", id).Find(&dept).Error
	if err != nil {
		return nil, err
	}
	if len(dept) == 0 {
		return nil, err
	}
	ancestorMenus, err := GetAncestorDept(dept[0].Fid)
	if err != nil {
		return nil, err
	}
	return append(ancestorMenus, dept...), nil
}
